Skip to content

linux: use screenshot portal for Wayland QR scanning - #4622

Open
waozixyz wants to merge 1 commit into
monero-project:masterfrom
waozixyz:qrcode
Open

linux: use screenshot portal for Wayland QR scanning#4622
waozixyz wants to merge 1 commit into
monero-project:masterfrom
waozixyz:qrcode

Conversation

@waozixyz

@waozixyz waozixyz commented Jul 1, 2026

Copy link
Copy Markdown

Fixes #4607

What changed

This updates OSHelper::grabQrCodesFromScreen() so the Transfer page's "Grab QR code from screen" action can work on Wayland.

On Wayland, QScreen::grabWindow(0) does not capture the desktop, so the
existing QR screen scan path silently failed. This PR detects Wayland on Linux
and uses org.freedesktop.portal.Screenshot instead. The existing
QScreen::grabWindow(0) path is still used for non-Wayland platforms.

The portal path:

  • asks the desktop portal for a screenshot using the standard user-consent
    prompt
  • waits for the portal response
  • loads the returned local screenshot URI
  • runs the existing QR decoder on that image
  • returns no QR codes if the request is cancelled, denied, times out, or the
    portal is unavailable

Why

Wayland intentionally blocks direct screen capture APIs like
QScreen::grabWindow(0). The XDG screenshot portal is the desktop-supported
way for applications to request a screenshot under Wayland while keeping user
consent in the flow.

This keeps the existing Transfer page behavior where possible, instead of
leaving the button doing nothing on Wayland.

Notes

This adds Qt5DBus on Linux desktop builds so the application can communicate with the XDG desktop portal.

@waozixyz
waozixyz force-pushed the master branch 2 times, most recently from 8a3f6b2 to f2eee93 Compare July 4, 2026 12:54

@thomasbuilds thomasbuilds left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This subscribes to Response only after the Screenshot call has returned. The portal can emit Response right behind the method reply (on failure paths), and although the signal is unicast (directed at the caller, so the bus delivers it without a match rule) QtDBus matches incoming signals against registered hooks at dispatch time and silently drops unmatched ones. Any Response dispatched before connect() registers the handler is discarded. So if the request fails fast (or the main thread is preempted between waitForFinished() and connect()), the response can be lost, and this then waits the full 60s with every window hidden.

The Request docs recommend passing a handle_token in the options, precomputing the request path (/org/freedesktop/portal/desktop/request/<sender>/<token>, where <sender> is the caller's unique name with the leading : stripped and . replaced by _), subscribing before the call, and verifying the returned handle matches (updating the subscription if it doesn't, for portals older than 0.9).

@waozixyz

waozixyz commented Jul 4, 2026

Copy link
Copy Markdown
Author

@thomasbuilds Good catch, I’ve updated this to use handle_token, subscribe to the expected request path before calling Screenshot, and keep the returned-handle fallback for older portals.

@plowsof

plowsof commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

a note for @selsta reg the Qt6 migration: https://doc.qt.io/qt-6/qtmultimedia-screencapture-example.html which should deprecate this PR will add another dependency, ignore for now!

@jpk68

jpk68 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

It looks like this PR removes ninja-build, even though we switched to Ninja in #4627. That should likely be added back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Grab QR from screen does not work in Wayland

4 participants